#include "plugin.h"
#include <stdio.h>
#include <stack>
#include <QtWidgets/QtWidgets>

std::ostream& operator<<(std::ostream& os, const QString& str) {
	   return os<<str.toLocal8Bit().constData();
}

struct Dialog: public QDialog {
	QTableWidget* table;
	void copyContent() {
		auto clipb=QGuiApplication::clipboard();
		QString s;
		QTextStream ss{&s};
		for(int i=0; i<table->rowCount(); i++) {
			ss<<table->item(i, 0)->text()<<'\t';
			ss<<table->item(i, 1)->text()<<'\t';
			auto it=table->item(i, 2);
			if(it) {
				ss<<table->item(i, 2)->text()<<'\n';
			} else {
				ss<<'\n';
			}
		}
		clipb->setText(s);
	}

	Dialog(int nrow, QWidget* par): QDialog{par} {
		auto vlayout=new QVBoxLayout{this};

		table=new QTableWidget{nrow, 3, this};
		vlayout->addWidget(table, 1);
		QStringList headers;
		headers<<"Index"<<"Name"<<"Annotation";
		table->setHorizontalHeaderLabels(headers);

		auto hlayout=new QHBoxLayout{};
		vlayout->addLayout(hlayout, 0);
		hlayout->addStretch(1);

		auto btn=new QPushButton{"&Copy", this};
		hlayout->addWidget(btn, 0);
		btn->setDefault(true);
		connect(btn, &QPushButton::clicked, this, &Dialog::copyContent);
	}

	void setAnnot(size_t row, size_t idx, const std::string& name, const std::string& annot) {
		table->setItem(row, 0, new QTableWidgetItem{QString::number(idx)});
		table->setItem(row, 1, new QTableWidgetItem{QString::fromStdString(name)});
		table->setItem(row, 2, new QTableWidgetItem{QString::fromStdString(annot)});
	}
};

struct AnnotSoma final: public GraphReader {
	AnnotSoma(): GraphReader{} { }
	~AnnotSoma() override { }
	std::string getAnnotPath(uint32_t id) {
		std::vector<const AnnotItem*> annots;
		auto n=annot(id);
		while(n) {
			annots.push_back(n);
			n=annot(n->par_idx);
		}
		if(annots.empty())
			return {};
		std::ostringstream oss;
		oss<<annots.back()->abbrev;
		annots.pop_back();
		while(!annots.empty()) {
			oss<<"\t";
			oss<<annots.back()->abbrev;
			annots.pop_back();
		}
		return oss.str();
	}

	void read(Graph gr, QWidget* par) override {
		std::vector<size_t> sels;
		for(auto n: gr.trees()) {
			if(n.selected())
				sels.push_back(n.index());
		}
		if(sels.empty()) {
			if(!gr.trees().empty()) {
				Dialog dlg(gr.trees().size(), par);
				for(size_t r=0; r<gr.trees().size(); r++) {
					auto n=gr.trees()[r];
					auto& p=n.root().point();
					auto i=xyzf2index_annot(p.x(), p.y(), p.z());
					dlg.setAnnot(r, n.index(), n.name(), getAnnotPath(i<0?0:cube_annot(i)));
				}
				dlg.exec();
			}
		} else {
			Dialog dlg(sels.size(), par);
			for(size_t r=0; r<sels.size(); r++) {
				auto n=gr.trees()[sels[r]];
				auto& p=n.root().point();
				auto i=xyzf2index_annot(p.x(), p.y(), p.z());
				dlg.setAnnot(r, n.index(), n.name(), getAnnotPath(i<0?0:cube_annot(i)));
			}
			dlg.exec();
		}
	}
	static GraphReaderInfo info;
	static GraphReader* creater() { return new AnnotSoma{}; }
};

struct ColoredAnnot final: public GraphReader {
	ColoredAnnot(): GraphReader{} { }
	~ColoredAnnot() override { }

	void read(Graph gr, QWidget* par) override {

		QFileDialog dlg(par, "Please choose a PNG file to save.", "", "");
		dlg.setAcceptMode(QFileDialog::AcceptSave);
		dlg.setDefaultSuffix("png");
		dlg.setFileMode(QFileDialog::AnyFile);
		dlg.setNameFilter("PNG files (*.png)");
		if(dlg.exec()!=QDialog::Accepted)
			return;

		auto z=depth_annot()/2;
		QImage img(width_annot(), height_annot(), QImage::Format_ARGB32);
		for(int32_t y=0; y<height_annot(); y++) {
			for(int32_t x=0; x<width_annot(); x++) {
				auto i=xyzi2index_annot(x, y, z);
				QRgb col{0};
				if(i>=0) {
					auto n=annot(cube_annot(i));
					if(n)
						col=qRgb(n->color_r, n->color_g, n->color_b);
				}
				img.setPixel(x, y, col);
			}
		}
		img.save(dlg.selectedFiles()[0]);
	}
	static GraphReaderInfo info;
	static GraphReader* creater() { return new ColoredAnnot{}; }
};

static void simple_load(std::vector<AlgorithmInfo*>& algs, std::vector<GraphReaderInfo*>& readers) {
	readers.push_back(new GraphReaderInfo{"Get Annotation of Soma", 12,
			"Get the annotation of all selected soma (all soma if none selected).",
			AnnotSoma::creater});
	readers.push_back(new GraphReaderInfo{"Get Colored Annotation Slice", 12,
			"Get a slice of colored annotation image.",
			ColoredAnnot::creater});
}

static void simple_unload() {
}

FNT_PLUGIN("AnnotSoma", &simple_load, &simple_unload, "Get Annotation of Soma");

